/**
* PropertyRMSReader.java
* @author NJ Pearman
* @date 3 Oct 2008
*
* This program is distributed under the terms of the GNU General Public
* License
* Copyright 2008 NJ Pearman
*
* This file is part of MobScrob.
*
* MobScrob is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MobScrob is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MobScrob. If not, see <http://www.gnu.org/licenses/>.
*/
package mobscrob.properties;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;
import javax.microedition.rms.RecordStoreNotOpenException;
import mobscrob.logging.Log;
import mobscrob.logging.LogFactory;
import mobscrob.util.StreamUtil;
import mobscrob.util.microedition.RecordStoreUtil;
/**
* @author Neill
*
*/
public class PropertyRMSPersistor implements PropertyPersistor {
private static final Log log = LogFactory.getLogger(PropertyRMSPersistor.class);
private static final String RECORD_STORE_NAME = "mobscrob.properties";
private static final int RS_INDEX_USERNAME = 1;
private static final int RS_INDEX_PASSWORD = 2;
private static final int RS_INDEX_SCROBBLE_OFFLINE = 3;
/* (non-Javadoc)
* @see mobscrob.properties.PropertyReader#load(mobscrob.properties.MobScrobProperties)
*/
public boolean load(MobScrobProperties properties) {
final String methodName = "1";
boolean success = true;
RecordStore rs = null;
try {
rs = RecordStore.openRecordStore(RECORD_STORE_NAME, true);
byte[] username = rs.getRecord(RS_INDEX_USERNAME);
properties.setUsername(getPropertyValue(username, KEY_USERNAME));
byte[] password = rs.getRecord(RS_INDEX_PASSWORD);
properties.setHashedPassword(getPropertyValue(password, KEY_HASHED_PASSWORD));
byte[] exportQueue = rs.getRecord(RS_INDEX_SCROBBLE_OFFLINE);
properties.setScrobbleOffline("true".equals(getPropertyValue(exportQueue, KEY_SCROBBLE_OFFLINE).toLowerCase()));
log.info(methodName, "Loaded RMS properties: "+properties.getUsername()+", "+properties.getHashedPassword());
} catch (RecordStoreFullException e) {
log.error(methodName, "No room in record store: "+e.getMessage(), e);
success = false;
} catch (RecordStoreNotFoundException e) {
log.error(methodName, "Record store doesn't exist: "+e.getMessage(), e);
success = false;
} catch (RecordStoreException e) {
log.error(methodName, "Problem with record store: "+e.getMessage(), e);
success = false;
} catch (IOException e) {
log.error(methodName, "Error reading from stream: "+e.getMessage(), e);
success = false;
} finally {
RecordStoreUtil.closeRecordStore(rs);
}
return success;
}
/* (non-Javadoc)
* @see mobscrob.properties.PropertyReader#save(mobscrob.properties.MobScrobProperties)
*/
public void save(MobScrobProperties properties) {
final String methodName = "2";
RecordStore rs = null;
try {
// open record store
rs = RecordStore.openRecordStore(RECORD_STORE_NAME, true);
// write properties to record store
byte[] username = getPropertyAsByteArray(KEY_USERNAME, properties.getUsername());
setProperty(rs, RS_INDEX_USERNAME, username);
byte[] pwd = getPropertyAsByteArray(KEY_HASHED_PASSWORD, properties.getHashedPassword());
setProperty(rs, RS_INDEX_PASSWORD, pwd);
byte[] exportQueue = getPropertyAsByteArray(KEY_SCROBBLE_OFFLINE, String.valueOf(properties.scrobbleOffline()));
setProperty(rs, RS_INDEX_SCROBBLE_OFFLINE, exportQueue);
} catch(IOException e) {
log.error(methodName, "Error writing to stream: "+e.getMessage(), e);
} catch (RecordStoreFullException e) {
log.error(methodName, "No room in record store: "+e.getMessage(), e);
} catch (RecordStoreNotFoundException e) {
log.error(methodName, "Record store doesn't exist: "+e.getMessage(), e);
} catch (RecordStoreException e) {
log.error(methodName, "Problem with record store: "+e.getMessage(), e);
} finally {
RecordStoreUtil.closeRecordStore(rs);
}
}
private void setProperty(RecordStore rs, int recordID, byte[] bytes) throws RecordStoreNotOpenException, RecordStoreFullException, InvalidRecordIDException, RecordStoreException {
final String methodName = "3";
if(rs.getNextRecordID() <= recordID) {
// add new record
rs.addRecord(bytes, 0, bytes.length);
log.info(methodName, "Added new property at "+recordID);
} else {
// update record
rs.setRecord(recordID, bytes, 0, bytes.length);
log.info(methodName, "Set existing property at "+recordID);
}
}
private byte[] getPropertyAsByteArray(String key, String value) throws IOException {
ByteArrayOutputStream baos;
DataOutputStream out = null;
try {
baos = new ByteArrayOutputStream();
out = new DataOutputStream(baos);
out.writeUTF(key);
out.writeUTF(value);
out.flush();
return baos.toByteArray();
} finally {
StreamUtil.closeOutputStream(out);
}
}
private String getPropertyValue(byte[] bytes, String keyName) throws IOException {
ByteArrayInputStream bais;
DataInputStream in = null;
String key, value;
try {
bais = new ByteArrayInputStream(bytes);
in = new DataInputStream(bais);
key = in.readUTF();
if(!keyName.equals(key)) {
throw new IOException("Property key not as expected. Wanted "+keyName+", got"+key);
}
value = in.readUTF();
return value;
} finally {
StreamUtil.closeInputStream(in);
}
}
}